#!/usr/bin/env python3
"""
RedFire Backend 结构验证脚本
==========================

验证新的微服务架构目录结构是否完整和规范
"""

import os
import sys
from pathlib import Path
from typing import Dict, List, Tuple, Optional
import json


class StructureValidator:
    """结构验证器"""
    
    def __init__(self, project_root: Path):
        self.project_root = project_root
        self.issues = []
        self.warnings = []
        self.success_count = 0
        self.total_checks = 0
    
    def validate_all(self) -> Dict:
        """执行所有验证"""
        print("🔍 开始验证RedFire Backend结构...")
        print("=" * 50)
        
        # 验证顶级目录结构
        self._validate_top_level_structure()
        
        # 验证微服务结构
        self._validate_services_structure()
        
        # 验证共享组件结构
        self._validate_shared_structure()
        
        # 验证基础设施配置
        self._validate_infrastructure_structure()
        
        # 验证脚本工具
        self._validate_scripts_structure()
        
        # 验证文档结构
        self._validate_docs_structure()
        
        # 验证配置文件
        self._validate_config_files()
        
        # 生成报告
        return self._generate_report()
    
    def _validate_top_level_structure(self):
        """验证顶级目录结构"""
        print("\n📁 验证顶级目录结构...")
        
        required_dirs = [
            "services",
            "shared", 
            "infrastructure",
            "scripts",
            "docs",
            "tests"
        ]
        
        required_files = [
            "README.md",
            "requirements.txt",
            "docker-compose.yml",
            "docker-compose.prod.yml",
            "Makefile",
            ".gitignore"
        ]
        
        # 检查目录
        for directory in required_dirs:
            self._check_directory_exists(directory, "顶级目录")
        
        # 检查文件
        for file in required_files:
            self._check_file_exists(file, "顶级配置文件")
    
    def _validate_services_structure(self):
        """验证微服务结构"""
        print("\n🚀 验证微服务结构...")
        
        expected_services = [
            "api-gateway",
            "user_service",
            "trading-service", 
            "market-data-service",
            "notification-service",
            "monitoring-service"
        ]
        
        services_dir = self.project_root / "services"
        if not services_dir.exists():
            self._add_issue("services目录不存在")
            return
        
        # 检查每个服务
        for service in expected_services:
            service_dir = services_dir / service
            if service_dir.exists():
                self._validate_single_service(service, service_dir)
            else:
                self._add_warning(f"微服务 {service} 不存在")
    
    def _validate_single_service(self, service_name: str, service_dir: Path):
        """验证单个微服务结构"""
        print(f"  📦 验证 {service_name}...")
        
        # 必需文件
        required_files = [
            "Dockerfile",
            "requirements.txt",
            "README.md"
        ]
        
        # 必需目录
        required_dirs = [
            "app"
        ]
        
        for file in required_files:
            file_path = service_dir / file
            if file_path.exists():
                self._success(f"{service_name}/{file}")
            else:
                self._add_issue(f"{service_name} 缺少 {file}")
        
        for directory in required_dirs:
            dir_path = service_dir / directory
            if dir_path.exists():
                self._success(f"{service_name}/{directory}/")
                # 验证app目录结构
                self._validate_service_app_structure(service_name, dir_path)
            else:
                self._add_issue(f"{service_name} 缺少 {directory} 目录")
    
    def _validate_service_app_structure(self, service_name: str, app_dir: Path):
        """验证服务app目录结构"""
        expected_structure = {
            "main.py": "应用入口文件",
            "api/": "API路由目录", 
            "models/": "数据模型目录",
            "schemas/": "Pydantic模式目录",
            "services/": "业务服务目录"
        }
        
        for item, description in expected_structure.items():
            item_path = app_dir / item
            if item.endswith("/"):
                # 目录
                if item_path.exists():
                    self._success(f"{service_name}/app/{item}")
                else:
                    self._add_warning(f"{service_name}/app 缺少 {item} ({description})")
            else:
                # 文件
                if item_path.exists():
                    self._success(f"{service_name}/app/{item}")
                else:
                    self._add_issue(f"{service_name}/app 缺少 {item} ({description})")
    
    def _validate_shared_structure(self):
        """验证共享组件结构"""
        print("\n🔗 验证共享组件结构...")
        
        shared_dir = self.project_root / "shared"
        if not shared_dir.exists():
            self._add_issue("shared目录不存在")
            return
        
        expected_components = [
            "core",
            "database",
            "cache", 
            "messaging",
            "auth",
            "logging",
            "monitoring",
            "utils",
            "config",
            "exceptions",
            "security",
            "validation"
        ]
        
        # 检查共享组件目录
        for component in expected_components:
            component_dir = shared_dir / component
            if component_dir.exists():
                self._success(f"shared/{component}/")
            else:
                self._add_warning(f"shared 缺少 {component} 组件")
        
        # 检查关键文件
        key_files = [
            "README.md",
            "__init__.py",
            "service_base.py",
            "dependencies.py"
        ]
        
        for file in key_files:
            file_path = shared_dir / file
            if file_path.exists():
                self._success(f"shared/{file}")
            else:
                self._add_issue(f"shared 缺少关键文件 {file}")
    
    def _validate_infrastructure_structure(self):
        """验证基础设施结构"""
        print("\n🏗️ 验证基础设施结构...")
        
        infra_dir = self.project_root / "infrastructure"
        if not infra_dir.exists():
            self._add_issue("infrastructure目录不存在")
            return
        
        expected_dirs = [
            "docker",
            "k8s", 
            "nginx",
            "monitoring"
        ]
        
        for directory in expected_dirs:
            dir_path = infra_dir / directory
            if dir_path.exists():
                self._success(f"infrastructure/{directory}/")
            else:
                self._add_warning(f"infrastructure 缺少 {directory} 目录")
    
    def _validate_scripts_structure(self):
        """验证脚本结构"""
        print("\n🔧 验证脚本结构...")
        
        scripts_dir = self.project_root / "scripts"
        if not scripts_dir.exists():
            self._add_issue("scripts目录不存在")
            return
        
        expected_dirs = [
            "deployment",
            "database",
            "utilities"
        ]
        
        for directory in expected_dirs:
            dir_path = scripts_dir / directory
            if dir_path.exists():
                self._success(f"scripts/{directory}/")
            else:
                self._add_warning(f"scripts 缺少 {directory} 目录")
        
        # 检查关键脚本
        key_scripts = [
            "deployment/deploy.py",
            "utilities/health_check.py",
            "utilities/create_service.py"
        ]
        
        for script in key_scripts:
            script_path = scripts_dir / script
            if script_path.exists():
                self._success(f"scripts/{script}")
            else:
                self._add_issue(f"scripts 缺少关键脚本 {script}")
    
    def _validate_docs_structure(self):
        """验证文档结构"""
        print("\n📚 验证文档结构...")
        
        docs_dir = self.project_root / "docs"
        if not docs_dir.exists():
            self._add_issue("docs目录不存在")
            return
        
        # 检查README
        readme_path = docs_dir / "README.md"
        if readme_path.exists():
            self._success("docs/README.md")
        else:
            self._add_issue("docs 缺少 README.md")
        
        # 检查架构文档
        arch_dir = docs_dir / "architecture"
        if arch_dir.exists():
            self._success("docs/architecture/")
            
            # 检查系统概览文档
            overview_path = arch_dir / "system-overview.md"
            if overview_path.exists():
                self._success("docs/architecture/system-overview.md")
            else:
                self._add_warning("docs/architecture 缺少 system-overview.md")
        else:
            self._add_warning("docs 缺少 architecture 目录")
    
    def _validate_config_files(self):
        """验证配置文件"""
        print("\n⚙️ 验证配置文件...")
        
        # 检查Docker Compose文件
        compose_files = [
            "docker-compose.yml",
            "docker-compose.prod.yml"
        ]
        
        for file in compose_files:
            file_path = self.project_root / file
            if file_path.exists():
                self._success(file)
                # 简单验证文件内容
                try:
                    content = file_path.read_text(encoding='utf-8')
                    if "version:" in content and "services:" in content:
                        self._success(f"{file} 格式正确")
                    else:
                        self._add_warning(f"{file} 格式可能有问题")
                except Exception as e:
                    self._add_warning(f"{file} 读取失败: {e}")
            else:
                self._add_issue(f"缺少配置文件 {file}")
        
        # 检查Makefile
        makefile_path = self.project_root / "Makefile"
        if makefile_path.exists():
            self._success("Makefile")
            try:
                content = makefile_path.read_text(encoding='utf-8')
                if "help:" in content and "quick-start:" in content:
                    self._success("Makefile 包含必要的目标")
                else:
                    self._add_warning("Makefile 可能缺少一些关键目标")
            except Exception as e:
                self._add_warning(f"Makefile 读取失败: {e}")
        else:
            self._add_issue("缺少 Makefile")
    
    def _check_directory_exists(self, directory: str, category: str):
        """检查目录是否存在"""
        dir_path = self.project_root / directory
        if dir_path.exists() and dir_path.is_dir():
            self._success(f"{directory}/")
        else:
            self._add_issue(f"{category} - 目录 {directory} 不存在")
    
    def _check_file_exists(self, file: str, category: str):
        """检查文件是否存在"""
        file_path = self.project_root / file
        if file_path.exists() and file_path.is_file():
            self._success(file)
        else:
            self._add_issue(f"{category} - 文件 {file} 不存在")
    
    def _success(self, item: str):
        """记录成功项"""
        self.success_count += 1
        self.total_checks += 1
        print(f"    ✅ {item}")
    
    def _add_issue(self, message: str):
        """添加问题"""
        self.issues.append(message)
        self.total_checks += 1
        print(f"    ❌ {message}")
    
    def _add_warning(self, message: str):
        """添加警告"""
        self.warnings.append(message)
        self.total_checks += 1
        print(f"    ⚠️  {message}")
    
    def _generate_report(self) -> Dict:
        """生成验证报告"""
        report = {
            "timestamp": __import__("time").time(),
            "total_checks": self.total_checks,
            "success_count": self.success_count,
            "issues_count": len(self.issues),
            "warnings_count": len(self.warnings),
            "issues": self.issues,
            "warnings": self.warnings,
            "success_rate": round(self.success_count / self.total_checks * 100, 2) if self.total_checks > 0 else 0
        }
        
        print("\n" + "=" * 50)
        print("📊 验证报告")
        print("=" * 50)
        print(f"总检查项: {self.total_checks}")
        print(f"成功项: {self.success_count}")
        print(f"问题数: {len(self.issues)}")
        print(f"警告数: {len(self.warnings)}")
        print(f"成功率: {report['success_rate']}%")
        
        if self.issues:
            print("\n❌ 发现问题:")
            for i, issue in enumerate(self.issues, 1):
                print(f"  {i}. {issue}")
        
        if self.warnings:
            print("\n⚠️  警告信息:")
            for i, warning in enumerate(self.warnings, 1):
                print(f"  {i}. {warning}")
        
        if not self.issues and not self.warnings:
            print("\n🎉 结构验证完全通过！")
        elif not self.issues:
            print("\n✅ 结构验证基本通过，但有一些警告需要注意。")
        else:
            print("\n⚠️  结构验证发现问题，建议修复后重新验证。")
        
        return report


def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description="RedFire Backend 结构验证工具")
    parser.add_argument(
        "--project-root", "-p",
        default=".",
        help="项目根目录路径"
    )
    parser.add_argument(
        "--output", "-o",
        help="输出报告文件路径(JSON格式)"
    )
    parser.add_argument(
        "--quiet", "-q",
        action="store_true",
        help="静默模式，只显示摘要"
    )
    
    args = parser.parse_args()
    
    # 验证项目根目录
    project_root = Path(args.project_root).resolve()
    if not project_root.exists():
        print(f"❌ 错误: 项目目录不存在: {project_root}")
        return 1
    
    # 执行验证
    validator = StructureValidator(project_root)
    
    if args.quiet:
        # 重定向输出到临时缓冲区
        import io
        import contextlib
        
        f = io.StringIO()
        with contextlib.redirect_stdout(f):
            report = validator.validate_all()
    else:
        report = validator.validate_all()
    
    # 保存报告
    if args.output:
        try:
            with open(args.output, 'w', encoding='utf-8') as f:
                json.dump(report, f, indent=2, ensure_ascii=False)
            print(f"\n📄 报告已保存到: {args.output}")
        except Exception as e:
            print(f"❌ 保存报告失败: {e}")
    
    # 返回退出码
    return 0 if len(validator.issues) == 0 else 1


if __name__ == "__main__":
    exit(main())
